package com.binyouwei.customize_compose_view.histogram

import android.util.Log
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.text.TextMeasurer
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.binyouwei.customize_compose_view.R

/**
 * @author 宾有为
 * @date 2024/7/24 14:58
 * @link https://blog.csdn.net/baidu_41616022?type=blog
 * @describe：
 **/
@Preview
@Composable
fun PreviewHistogram() {
    val data =
        remember {
            listOf(
                HistogramData("1月", 10f),
                HistogramData("2月", 25f),
                HistogramData("3月", 20f),
                HistogramData("4月", 58f),
                HistogramData("5月", 25f),
                HistogramData("6月", 45f),
                HistogramData("7月", 97f),
                HistogramData("8月", 55f),
                HistogramData("9月", 32f),
                HistogramData("10月", 68f),
                HistogramData("11月", 88f),
                HistogramData("12月", 16f)
            )
        }
    Histogram(data, Modifier.width(400.dp).height(400.dp))
}

@Composable
fun Histogram(
    data: List<HistogramData>, modifier: Modifier = Modifier
) {
    Box(
        modifier = Modifier
            .wrapContentSize()
            .padding(16.dp),
    ) {
        BarChart(
            data,
            modifier = modifier
                .width(400.dp)
                .height(400.dp)
        )
    }
}

@Composable
internal fun BarChart(
    data: List<HistogramData>,
    modifier: Modifier = Modifier,
    barColors: Color = colorResource(R.color.columnar),
    barBackground: Color = colorResource(R.color.columnar_background)
) {
    val textMeasurer = rememberTextMeasurer()
    Canvas(modifier) {
        // 画柱状、x 轴的文字
        drawColumnar(this, data, barColors, barBackground, textMeasurer)
        // 画 y 轴
        drawYAxis(this, textMeasurer, data)
    }
}

/**
 * 绘制柱状
 */
internal fun drawColumnar(
    drawScope: DrawScope,
    data: List<HistogramData>,
    barColors: Color,
    barbackground: Color,
    textMeasurer: TextMeasurer
) {
    val maxDataValue = data.maxOf { it.data }
    val size = drawScope.size

    val dataSize = data.size + 1
    val barWidth =
        (size.width - (ColumnarDistance.SPACE_BETWEEN_BARS.distance * dataSize) - ColumnarDistance.RIGHT.distance) / dataSize
    data.forEachIndexed { index, value ->
        val drawHeight =
            size.height - ColumnarDistance.BOTTOM.distance - ColumnarDistance.TOP.distance
        val barHeight = ((value.data / maxDataValue) * drawHeight)
        val xOffset = (index + 1) * (barWidth + ColumnarDistance.SPACE_BETWEEN_BARS.distance)
        val yOffset = (size.height - ColumnarDistance.BOTTOM.distance) - barHeight
        // 绘制柱状的背景
        drawScope.drawRoundRect(
            // 设置柱状的背景色
            color = barbackground,
            // 在左上方开始绘制的起点
            topLeft = Offset(
                xOffset,
                ColumnarDistance.TOP.distance
            ),
            // 从 topLeft 绘制的起点开始算起，应该绘制多高、多宽的矩形
            size = Size(barWidth, drawHeight)
        )
        // 绘制柱状
        drawScope.drawRoundRect(
            // 设置柱状的背景色
            color = barColors,
            // 在左上方开始绘制的起点
            topLeft = Offset(
                xOffset,
                yOffset
            ),
            // 从 topLeft 绘制的起点开始算起，应该绘制多高、多宽的矩形
            size = Size(barWidth, barHeight)
        )
        // 绘制柱状下边的文字
        drawScope.drawText(
            textMeasurer,
            value.name,
            // 在左上方开始绘制的起点
            topLeft = Offset(xOffset, yOffset + barHeight),
            style = TextStyle(color = Color.Gray, fontSize = 12.sp)
        )
    }
}

internal fun drawYAxis(
    drawScope: DrawScope,
    textMeasurer: TextMeasurer,
    data: List<HistogramData>
) {
    val listY = listOf(0f, 0.25f, 0.5f, 0.75f, 1f)
    val size = drawScope.size
    val textMax = data.maxOf { it.data }

    listY.forEachIndexed { index, percentage ->
        val yAxisHeight =
            (size.height - ColumnarDistance.TOP.distance - ColumnarDistance.BOTTOM.distance) * percentage
        // 绘制 y 轴文字
        drawScope.drawText(
            textMeasurer,
            (textMax * (1 - percentage)).toInt().toString(),
            style = TextStyle(color = Color.Gray, fontSize = 12.sp),
            topLeft = Offset(
                0f,
                yAxisHeight + 15
            )
        )
        // 绘制 y 轴横线
        drawScope.drawLine(
            color = if (listY[index] == 1f) Color.Black else Color.Gray,
            // 绘制线的起点
            Offset(
                ColumnarDistance.LEFT_Y_X.distance,
                yAxisHeight + ColumnarDistance.TOP.distance
            ),
            // 绘制线的终点
            Offset(
                size.width,
                yAxisHeight + ColumnarDistance.TOP.distance
            ),
            strokeWidth = 1f
        )
    }
}